﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace CF.Utils.GameTerminal
{
    public enum GameTerminalExecuteResult
    {
        UnExceptionError = -1,
        Succeed = 0,
        NullCmd = 1,
        BadCmd = 2,
        ClassNotFound = 3,
        MethodNotFound = 4
    }

    public static class GameTerminal
    {
        static GameTerminal()
        {
            // Log.Info("Game Terminal Static");
            if (attributeTypes == null)
            {
                attributeTypes = new Dictionary<string, Type>();
            }
        }

        private static Dictionary<string, Type> attributeTypes;

        public static void GetAllAttributeMethods()
        {
            var assembly = Assembly.Load("Assembly-CSharp");
            var types = assembly.GetTypes();

            attributeTypes?.Clear();

            foreach (var type in types)
            {
                if (!type.IsClass)
                {
                    continue;
                }

                foreach (var methodInfo in type.GetMethods())
                {
                    if (methodInfo.IsDefined(typeof(GameTerminalAttribute)))
                    {
                        if (attributeTypes != null && !attributeTypes.ContainsKey(type.Name))
                        {
                            var key = $"{type.FullName}.{methodInfo.Name}";
                            attributeTypes.Add(key, type);
                        }
                    }
                }
            }
        }

        public static GameTerminalExecuteResult ExecuteTerminalCmd(string cmd)
        {
            if (string.IsNullOrEmpty(cmd))
            {
                return GameTerminalExecuteResult.NullCmd;
            }

            var cmds = cmd.Split('.');
            var nameSpace = string.Empty;
            var className = string.Empty;
            var methodName = string.Empty;
            if (cmds.Length < 2)
            {
                return GameTerminalExecuteResult.BadCmd;
            }

            if (cmds.Length == 2)
            {
                className = cmds[0];
                methodName = cmds[1];
            }
            else if (cmds.Length == 3)
            {
                nameSpace = cmds[0];
                className = cmds[1];
                methodName = cmds[2];
            }
            else
            {
                className = cmds[cmds.Length - 2];
                methodName = cmds[cmds.Length - 1];
                nameSpace = cmd.Substring(0, cmd.Length - className.Length - methodName.Length - 2);
            }

            // Log.Info(nameSpace + " " + className + " " + methodName);
            if (attributeTypes.TryGetValue(cmd, out Type type))
            {
                foreach (var method in type.GetMethods())
                {
                    if (method.Name.Equals(methodName))
                    {
                        if (method.IsStatic)
                        {
                            method.Invoke(null, null);
                        }
                        else
                        {
                            object obj = Activator.CreateInstance(type);
                            method.Invoke(obj, null);
                        }

                        return GameTerminalExecuteResult.Succeed;
                    }
                }

                return GameTerminalExecuteResult.MethodNotFound;
            }
            else
            {
                // TODO
                return GameTerminalExecuteResult.ClassNotFound;
            }

            // return GameTerminalExecuteResult.UnExceptionError;
        }
    }
}